package com.rc.scripting.plugin;

import javax.script.Compilable;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

/**
 * <p>
 * This is the runtime-environment for the plugin-framework
 * it provides script-engine of 3 types:
 * 
 * <li>normal script engine</li>
 * <li>compilable script engine</li>
 * <li>invocable script engine</li>
 * 
 * </p>
 * 
 * <p>
 * There is only one instance of runtime-env in the framework in
 * the run-time. Any other thread could <code>getInstance</code>
 * of <b>RuntimeEnv</b>.
 * </p>
 * @author juntao.qiu@gmail.com
 *
 */
public class RuntimeEnv {
	public static final String ENGINE_NAME = "javascript";
	private static RuntimeEnv instance;
	
	private Compilable scriptEngine;
	
	private RuntimeEnv(){
		ScriptEngineManager manager = new ScriptEngineManager();
		System.out.println(manager);
		scriptEngine = (Compilable) manager.getEngineByName(ENGINE_NAME);
	}
	
	public static RuntimeEnv getInstance(){
		if(instance == null){
			instance = new RuntimeEnv();
		}
		return instance;
	}
	
	/**
	 * the normal type of script engine
	 * @return
	 */
	public ScriptEngine getScriptEngine(){
		return (ScriptEngine)scriptEngine;
	}
	
	/**
	 * convert the script engine to compilable
	 * @return
	 */
	public Compilable getCompilableEngine(){
		return (Compilable)scriptEngine;
	}
	
	/**
	 * convert the script engine to invocable
	 * @return
	 */
	public Invocable getInvocableEngine(){
		return (Invocable)scriptEngine;
	}
	
	/**
	 * execute a function defined in script, and pass them
	 * the arguments list.
	 */
	public Object invokeFunction(String func, Object... args){
		Object result = null;
		try {
			result = getInvocableEngine().invokeFunction(func, args);
		} catch (ScriptException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
		
		return result;
	}
}
